package tools;

import datatypes.Edge;
import datatypes.OrientedLine2D;
import datatypes.Triangle;
import datatypes.Vertex;

/**
 * 
 * @author PSeiferth
 *
 */
public class Tool {

	/**
	 * Calculates the intersection point of two oriented Lines. 
	 * @param line1
	 * @param line2
	 * @return 
	 * 		The intersection point if it exists, null otherwise.
	 */
	static Vertex computeLineIntersectionPoint(OrientedLine2D line1, OrientedLine2D line2) {
		
		//y = mx + n
		double m1 = line1.getSlope();
		double m2 = line2.getSlope();
		double n1 = line1.getYIntercept();
		double n2 = line2.getYIntercept();
		
		// if the slope is the same the two lines are the same or in parallel to each other
		if (m1 == m2) {
			return null;
		}
		
		double x = (n2 - n1) / (m1 - m2);
		double y = m1*x + n1;
		
		return new Vertex(x,y);
	}
	
	/** 
	 This method calculates the "point determinant" of three 2D vectors.
	 
	 AKA Orientation test, isLeftOf, isClockwise...
	 The Vectors p, q, r are used to 
	 compute the determinant of the following matrix:<br>
	 \f[
	 \begin{pmatrix}
	 p.x & q.x & r.x\\
	 p.y & q.y & r.y\\
	 1 & 1 & 1
	 \end{pmatrix}
	 \f]
	 
	 Point r is on p->q if the result is 0. If not, r is increasingly
	 farther away from p->q, left from that line if result > 0, right otherwise.
	 Oh, btw: Result/2 yields the area of the triangle.
	 @param		p   The 1st vector
	 @param		q   The 2nd vector
	 @param		r   The 3rd vector
	 @result
	 */
	public static double leftOfTest(Vertex p, Vertex q, Vertex r) {
		return (q.getX() - p.getX()) * (r.getY() - p.getY()) - (r.getX() - p.getX()) * (q.getY() - p.getY());
	}
	
	public static double leftOfTest(double px, double py, double qx, double qy, double rx, double ry) {
      return (qx - px) * (ry - py) - (rx - px) * (qy - py);
}
	
	/** 
	 Calls {@link #leftOfTest(Vertex, Vertex, Vertex)} to perform the leftOfTest with
	 p = line.getStartPoint() and q = line.getEndPoint().
	 @param		line
	 @param		r   The 3rd vector
	 @result
	 */
	public static double leftOfTest(OrientedLine2D line, Vertex r) {
		return leftOfTest(line.getStartPoint(), line.getEndPoint(), r);
	}
	
	/** 
	 Calls {@link #leftOfTest(Vertex, Vertex, Vertex)} to perform the leftOfTest with
	 p = edge.getPoint1() and q = edge.getPoint2().
	 @param		edge
	 @param		r   The 3rd vector
	 @result
	 */
	public static double leftOfTest(Edge edge, Vertex r) {
		return leftOfTest(edge.getVertex1(), edge.getVertex2(), r);
	}
	
	/**
	 * Joins the two passed-in triangles on the shared edge, then takes
	 * a look at the resulting polygon to see if it is convex.
	 * 
	 * @param points The set of points
	 * @return The list with all edges within the skeleton in them
	 */
	public static boolean quadIsConvex(Triangle t1, Triangle t2, Edge sharedEdge) {
		
		Vertex t1OffVertex = t1.getVertexNotOnEdge(sharedEdge);
		Vertex t2OffVertex = t2.getVertexNotOnEdge(sharedEdge);
		
		return quadIsConvex(t1OffVertex, t2OffVertex, sharedEdge);
	}
	
	/**
	 * Checks whether the polygon formed by the two vertices and the two
	 * end points of the edge form a convex polygon.
	 * 
	 * @param points The set of points
	 * @return The list with all edges within the skeleton in them
	 */
	public static boolean quadIsConvex(Vertex v1, Vertex v2, Edge sharedEdge) {
		return sharedEdge.intersectsLineThroughVertices(v1, v2, -0.000001);
	}

}
